<?php
namespace app\api\controller\books;


use fast\Random;
use OSS\OssClient;
use think\Config;
use think\Controller;
use think\Db;
use think\File;
use think\Image;
use think\Request;
use \think\Validate;

/**
 * Created by Botter.
 * User: Botter
 * Time: 2018/4/15 0015 10:26
 */
class Base extends Controller
{
    public static $rule = [

    ];
    public $ERROR = 'error';
    public $INFO = 'info';
    public $DEBUG = 'debug';
    protected $ROOT = '';
    protected $request;//用来处理参数
    protected $validater;//用来验证数据/参数
    protected $params;//过滤后服符合要求的参数
    protected $rules = [];

    protected function _initialize()
    {
        parent::_initialize();
        header('Access-Control-Allow-Origin:*');
        header("Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE");
        header('Access-Control-Allow-Headers:X-Requested-With,Content-Type,Range');
        header('Access-Control-Expose-Headers:Accept-Range,Content-Encoding,Content-Length,Content-Range');
        $this->request = Request::instance();
//        $this->ROOT = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'] . '/public';

        //$this->getheader($this->request->header());
        //$this->check_time($this->request->only(['time']));1
        //$this->check_token($this->request->param());
        $this->params = $this->check_params($this->request->param(true));
        (isset($this->params['page'])) || $this->params['page'] = 1;
        (isset($this->params['pagesize'])) || $this->params['pagesize'] = 10;
        $this->params['page_limit'] = $this->params['page'] . ',' . $this->params['pagesize'];
//        $this->auto_close_order();
    }


    /**
     * 验证请求是否超时
     * @param  [int] $arr [包含时间戳的参数数组]
     * @return [json]       [检测结果]
     */
    public function check_time($arr)
    {
        if (!isset($arr['time']) || intval($arr['time']) <= 1) {
            $this->return_msg(400, '时间戳不正确!');
        }
        if (time() - intval($arr['time']) > 60) {
            $this->return_msg(401, '请求超时!');
        }

    }

    public function db_api_log($msg,$detail, $level) {
        if (!$level) {
            $level = $this->INFO;
        }
        db('api_log')->insert([
            "module" => $this->request->module(),
            "controller" => $this->request->controller(),
            "action" => $this->request->action(),
            "url"=>$this->request->url(),
            "param"=>json_encode($this->request->param(), JSON_UNESCAPED_UNICODE),

            "level" => $level,
            "msg" => $msg,
            "detail" => $detail,
        ]);
    }

    /**
     * api数据返回
     * @param  [int] $code [结果码 200：正常、4**数据问题/5**服务器问题]
     * @param [string] $msg [接口要返回的展示信息]
     * @param [array] $data [接口要返回的数据]
     * @return [json]  [最终的json数据]
     */
    public function return_msg($code, $msg = '', $data = [], $totalnum = -1)
    {
        header('Content-Type: application/json');
        /********* 组合数据 ********/
        $return_data['code'] = $code;
        $return_data['msg'] = $msg;
        $return_data['data'] = $data;

//        if ($totalpage != 0) {
//            $return_data['totalpage'] = $totalpage;
//        }
        if ($totalnum >= 0) {
            $totalPage = $totalnum % $this->params['pagesize'] == 0
                ? $totalnum / $this->params['pagesize'] : (int)($totalnum / $this->params['pagesize']) + 1;
            $return_data['pagenum'] = intval($this->params['page']);
            $return_data['pagesize'] = intval($this->params['pagesize']);
            $return_data['totalnum'] = $totalnum;
            $return_data['totalpage'] = $totalPage;
        }
        /********* 返回信息并终止脚本 ********/
        header("HTTP/1.0 200 OK");
        echo json_encode($return_data);

        die;
    }

    /**
     * 验证token（防止篡改数据）
     * @param  [array] $arr [全部请求参数]
     * @return [json]       [token验证结果]
     */
    public function check_token($arr)
    {
        /************* api传过来的token ***************/
        if (!isset($arr['token']) || empty($arr['token'])) {
            $this->return_msg(400, 'token不能为空!');
        }
        $app_token = $arr['token'];//api传过来的token
        /************* 服务端生成token ***************/
        unset($arr['token']);
        $server_token = '';
        foreach ($arr as $key => $value) {
            $server_token .= md5($value);
        }
        $server_token = md5('api_' . $server_token . '_api');//服务器端即时生成的token
        if ($app_token !== $server_token) {
            $this->return_msg(400, 'token不正确!');
        }
    }

    /**
     * 验证access_token（）
     * @param  [array] $arr [全部请求参数]
     * @return [json]       [token验证结果]
     */
    public function check_access_token($arr)
    {
        /************* api传过来的token ***************/
        if (!isset($arr['access_token']) || empty($arr['access_token'])) {
            $this->return_msg(408, 'access_token不能为空!');
        }
        $app_token = $arr['access_token'];//api传过来的token
        /************* 验证access_token ***************/
        $res = db('oauth_users')->where('oauth_user_access_token', $arr['access_token'])->find();
        if ($res) {
            $arr['uid'] = $res['oauth_user_id'];
            return $arr;
        } else {
            $this->return_msg(410, '无效的access_token!');
        }
    }

    /**
     * 验证参数 参数过滤
     * @param  [array] $arr [除time和token外的所有参数]
     * @return [return]      [合格的参数数组]
     */
    public function check_params($arr)
    {
        $controller = get_called_class();
        $action = $this->request->action();
        if ($controller == 'app\green\base\Base') {
            $rule = $this->rules;
        } else {
            $rule = $controller::$rule;
        }
        $action = strtolower($action);
        $rule = array_change_key_case($rule, CASE_LOWER);
        if (!isset($rule[$action])) {
            return $arr;
        }
        $rule = $rule[$action];
        /*********** 获取参数的验证规则  ***********/
//        $rule = $this->rules[$this->request->controller()][$this->request->action()];
        /*********** 验证参数并返回错误  ***********/
        $this->validater = new Validate($rule);
        if (!$this->validater->check($arr)) {
            $this->return_msg(400, $this->validater->getError());
        }
        /*********** 如果正常,通过验证  ***********/
        return $arr;
    }



    function mkdirs_r($path, $mode = 0777){
        if(is_dir($path)){
            return '无法创建,已经是目录了';
        }else{
            if(mkdir($path, $mode, true)) {
                return '创建成功';
            }else{
                return '创建失败';
            }
        }
    }





    /**
     * 根据传入的属性数组从求情返回数组
     * @param string $tableName
     * @return array $model
     */
    protected function getModel($tableName)
    {
        $fields = db($tableName, [], false)->getTableInfo('', 'fields');
        $model = array();
        foreach ($fields as $pro) {
            if (isset($this->params[$pro])) {
                $model[$pro] = $this->params[$pro];
            }
        }
        return $model;
    }

    /**
     * 上传文件
     */
    public function uploadFile()
    {
        Config::set('default_return_type', 'json');
        $file = $this->request->file('file');
        if (empty($file)) {
            $this->return_msg(400,'未指定上传文件file');
//            $this->error(__('No file upload or server upload limit exceeded'));
        }

        //判断是否已经存在附件
        $sha1 = $file->hash();

        $upload = Config::get('upload');

        preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
        $type = strtolower($matches[2]);
        $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
        $size = (int)10 * pow(1024, isset($typeDict['m']) ? $typeDict['m'] : 0);
        $fileInfo = $file->getInfo();
        $suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
        $suffix = $suffix ? $suffix : 'file';

        $mimetypeArr = explode(',', strtolower($upload['mimetype']));
        $mimetypeArr=array_merge($mimetypeArr,['mp4','mp3','avi','flv','wmv']);
        $typeArr = explode('/', $fileInfo['type']);

        //验证文件后缀
        if ($upload['mimetype'] !== '*' &&
            (
                !in_array($suffix, $mimetypeArr)
                || (stripos($typeArr[0] . '/', $upload['mimetype']) !== false && (!in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr)))
            )
        ) {
            $this->return_msg(400,'Uploaded file format is limited');

        }
        $replaceArr = [
            '{year}'     => date("Y"),
            '{mon}'      => date("m"),
            '{day}'      => date("d"),
            '{hour}'     => date("H"),
            '{min}'      => date("i"),
            '{sec}'      => date("s"),
            '{random}'   => Random::alnum(16),
            '{random32}' => Random::alnum(32),
            '{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
            '{suffix}'   => $suffix,
            '{.suffix}'  => $suffix ? '.' . $suffix : '',
            '{filemd5}'  => md5_file($fileInfo['tmp_name']),
        ];
        $savekey = $upload['savekey'];
        $savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);

        $uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
        $fileName = substr($savekey, strripos($savekey, '/') + 1);
        //
        $splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
        if ($splInfo) {
            $imagewidth = $imageheight = 0;
            if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf'])) {
                $imgInfo = getimagesize($splInfo->getPathname());
                $imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth;
                $imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight;
            }
            $params = array(
                'filesize'    => $fileInfo['size'],
                'imagewidth'  => $imagewidth,
                'imageheight' => $imageheight,
                'imagetype'   => $suffix,
                'imageframes' => 0,
                'mimetype'    => $fileInfo['type'],
                'url'         => $uploadDir . $splInfo->getSaveName(),
                'uploadtime'  => time(),
                'storage'     => 'local',
                'sha1'        => $sha1,
            );
            $attachment = model("attachment");
            $attachment->data(array_filter($params));
//            $attachment->save();


            $OssPath = "https://gzns.oss-cn-shenzhen.aliyuncs.com/";
            $accessKeyId = "LTAI9HrmZP59xIU4";
            $accessKeySecret = "0BCM2fQBbS1cjVRJuTAiDaltGiwXDB";
//        $endpoint = "http://oss-cn-shenzhen-internal.aliyuncs.com";   //内网
            $endpoint = "https://oss-cn-shenzhen.aliyuncs.com";
            // 存储空间名称
            $bucket = "gzns";
            try {
                $url = $attachment->getData('url');
                $file = new File(ROOT_PATH . 'public' . $url);
                $fileName = $file->getFilename();

                $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
//                $ossClient->createBucket($bucket);
                $result = $ossClient->uploadFile($bucket, $fileName, $file->getPathname());
                if ($result && $result['info'] && $result['info']['http_code'] == 200) {
                    $this->return_msg(200,'',["url" => $OssPath . $fileName]);

                }
            } catch (OssException $e) {
//            print $e->getMessage();
                $this->return_msg(200,'上传失败');


            }
        } else {
            // 上传失败获取错误信息
//            $this->error($file->getError());
            $this->return_msg(400,$file->getError());

        }


    }


}

